In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

sns.set(style='whitegrid', font_scale=1.3, palette='Set2')
%matplotlib inline

import plotly
import plotly.express as px

import requests
from time import sleep
from tqdm import tqdm
import json

Второй курс — самое время задуматься о будущей профессии и проанализировать существующие предложения. Дело тут даже не в том, чтобы найти интересную стажировку. В первую очередь сейчас стоит подумать о том, в какую сторону развиваться дальше. Например, если вы хотите работать в какой-либо конкретной профессии, то наверняка стоит развивать какие-то определенные навыки, и даже выбрать подходящую кафедру. Анализ существующих вакансий поможет определить, какие навыки вам нужны.

В данном задании вам нужно проанализировать вакансии на сайте hh.ru с использованием официального API.


Справка по работе с API.¶

Внимание! При работе с API не забывайте делать паузы между запросами, чтобы не задудосить сервер HeadHunter. Если вас заблокируют, это не будет являться уважительной причиной переноса дедлайна.

Мы будем работать только с вакансиями. Для этого не требуется регистрироваться и получать токен. Ниже приведен краткий пример работы с API. Подробное описание работы с вакансиями, включая параметры запросов и формат ответа можно почитать в документации.

Например, мы хотим найти вакансии по запросу Data Scientist в Москве. Тогда первую страницу поиска из 10 вакансий на страницу мы можем получить с запроса к API:

In [2]:
URL = 'https://api.hh.ru/vacancies'

params = {
    'text': "Data Scientist",
    'area': 1,
    'page': 0,
    'per_page': 10
}

req = requests.get(URL, params)
data = json.loads(req.content.decode())

Если все прошло успешно, полученный словарь будет иметь следующие ключи

In [ ]:
data.keys()
Out[ ]:
dict_keys(['items', 'found', 'pages', 'per_page', 'page', 'clusters', 'arguments', 'alternate_url'])

Можем посмотреть на краткое описание первой вакансии

In [ ]:
data['items'][0]
Out[ ]:
{'id': '49423067',
 'premium': False,
 'name': 'Data Scientist',
 'department': None,
 'has_test': False,
 'response_letter_required': False,
 'area': {'id': '1', 'name': 'Москва', 'url': 'https://api.hh.ru/areas/1'},
 'salary': {'from': None, 'to': 390000, 'currency': 'RUR', 'gross': False},
 'type': {'id': 'open', 'name': 'Открытая'},
 'address': None,
 'response_url': None,
 'sort_point_distance': None,
 'published_at': '2022-03-17T12:37:57+0300',
 'created_at': '2022-03-17T12:37:57+0300',
 'archived': False,
 'apply_alternate_url': 'https://hh.ru/applicant/vacancy_response?vacancyId=49423067',
 'insider_interview': None,
 'url': 'https://api.hh.ru/vacancies/49423067?host=hh.ru',
 'alternate_url': 'https://hh.ru/vacancy/49423067',
 'relations': [],
 'employer': {'id': '2324020',
  'name': 'Точка',
  'url': 'https://api.hh.ru/employers/2324020',
  'alternate_url': 'https://hh.ru/employer/2324020',
  'logo_urls': {'240': 'https://hhcdn.ru/employer-logo/3414734.jpeg',
   '90': 'https://hhcdn.ru/employer-logo/3414733.jpeg',
   'original': 'https://hhcdn.ru/employer-logo-original/743443.jpg'},
  'vacancies_url': 'https://api.hh.ru/vacancies?employer_id=2324020',
  'trusted': True},
 'snippet': {'requirement': 'Есть опыт работы с методами машинного обучения и основными инструментами <highlighttext>data</highlighttext> science: Scikit-learn, XGBoost, CatBoost и т.п. ',
  'responsibility': 'Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний...'},
 'contacts': None,
 'schedule': {'id': 'fullDay', 'name': 'Полный день'},
 'working_days': [],
 'working_time_intervals': [],
 'working_time_modes': [],
 'accept_temporary': False}

Сколько всего найдено вакансий

In [ ]:
data['found']
Out[ ]:
285

Количество страниц в результатах поиска

In [ ]:
data['pages']
Out[ ]:
29

Из результатов можем сделать удобную таблицу, причем в дальнейшем можно оставить только те колонки, которые необходимы для анализа.

In [ ]:
df = pd.json_normalize(data['items'])
df.head()
Out[ ]:
id premium name department has_test response_letter_required address response_url sort_point_distance published_at ... address.raw address.metro.station_name address.metro.line_name address.metro.station_id address.metro.line_id address.metro.lat address.metro.lng address.metro_stations address.id address.metro
0 49423067 False Data Scientist NaN False False NaN None None 2022-03-17T12:37:57+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 53929493 True Data Scientist (CV+NLP) NaN False False NaN None None 2022-03-16T12:35:21+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 53947371 True Data Scientist (Корпоративный бизнес) NaN False False NaN None None 2022-03-16T17:25:13+0300 ... Москва, Кутузовский проспект, 32к1 Кутузовская Филевская 4.73 4 55.740544 37.534100 [{'station_name': 'Кутузовская', 'line_name': ... 731097 NaN
3 53809111 False Data scientist / Product analyst NaN False False NaN None None 2022-03-17T11:45:23+0300 ... Москва, Нижняя Красносельская улица, 35с9 Бауманская Арбатско-Покровская 3.17 3 55.772405 37.679040 [{'station_name': 'Бауманская', 'line_name': '... 743543 NaN
4 53211742 False Junior Data scientist/ Младший риск-аналитик NaN False True NaN None None 2022-03-16T11:16:44+0300 ... Москва, улица 8 Марта, 1с12 Динамо Замоскворецкая 2.34 2 55.789704 37.558212 [{'station_name': 'Динамо', 'line_name': 'Замо... 1551673 NaN

5 rows × 63 columns

Для получения полного описания вакансии потребуется задать отдельный запрос, используя ее id.

In [ ]:
vacancy = df['id'].iloc[0]
vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'

req = requests.get(vacancy_url)
vacancy_info = json.loads(req.content.decode())
In [ ]:
vacancy_info
Out[ ]:
{'id': '49423067',
 'premium': False,
 'billing_type': {'id': 'standard_plus', 'name': 'Стандарт плюс'},
 'relations': [],
 'name': 'Data Scientist',
 'insider_interview': None,
 'response_letter_required': False,
 'area': {'id': '1', 'name': 'Москва', 'url': 'https://api.hh.ru/areas/1'},
 'salary': {'from': None, 'to': 390000, 'currency': 'RUR', 'gross': False},
 'type': {'id': 'open', 'name': 'Открытая'},
 'address': None,
 'allow_messages': True,
 'site': {'id': 'hh', 'name': 'hh.ru'},
 'experience': {'id': 'between3And6', 'name': 'От 3 до 6 лет'},
 'schedule': {'id': 'fullDay', 'name': 'Полный день'},
 'employment': {'id': 'full', 'name': 'Полная занятость'},
 'department': None,
 'contacts': None,
 'description': '<p>Ищем специалиста по Data Science, чтобы строить и улучшать модели машинного обучения, которые помогут усовершенствовать наш продукт и внутренние процессы. Мы стремимся к тому, чтобы мы стали быстрее и удобнее для клиентов. И в этом нам нужна твоя помощь.</p> <p><strong>Что нужно делать</strong></p> <p>Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний по данным о бизнесе.</p> <p>Ты будешь доставать данные из баз и других источников, приводить их к нужному виду, анализировать и затем строить модели. Тебе предстоит планировать и ставить эксперименты, анализировать результаты и их статистическую значимость. Использовать feature engineering, model selection и fine tuning.</p> <p><strong>Ты подойдешь, если</strong></p> <ul> <li> <p>Знаешь Python, умеешь обрабатывать данные с помощью pandas, NumPy, Plotly.</p> </li> <li> <p>У тебя есть опыт работы с SQL.</p> </li> <li> <p>Есть опыт работы с методами машинного обучения и основными инструментами data science: Scikit-learn, XGBoost, CatBoost и т.п.</p> </li> <li> <p>Разбираешься в математической статистике, теории вероятностей и знаешь, как проводить A/B тестирования.</p> </li> </ul> <p><strong>Будет плюсом, если</strong></p> <ul> <li> <p>Ты понимаешь принципы работы нейросетей и уже имеешь опыт с одним или несколькими фреймворками для глубокого обучения: TensorFlow или PyTorch.</p> </li> <li> <p>Умеешь вводить модели машинного обучения в работу production.</p> </li> </ul> <p><strong>Что будет твоим в Точке</strong></p> <ul> <li> <p>Зарплата от 100 000 ₽. Расскажи на собеседовании, какая зарплата будет комфортной для тебя. А мы определим твой грейд по хард и софт скиллам и назовём точную сумму.</p> </li> <li> <p>Официальное трудоустройство и бесплатная страховка здоровья даже за границей.</p> </li> <li> <p>Удобный график: гибкое начало и окончание рабочего дня.</p> </li> <li> <p>Современный и уютный офис со спортзалом и библиотекой, кофе-поинтами, кухнями и зонами отдыха.</p> </li> <li> <p>Гибкие методы управления: мы используем Agile и SCRUM, чтобы каждый день создавать новое и быстро реагировать на изменения.</p> </li> <li> <p>Бесплатное корпоративное обучение: мы ездим на IT-конференции, собираемся на митапы, раздаем призы на хакатонах и проходим курсы за счёт компании.</p> </li> <li> <p>Возможность принимать решения без тысячи согласований и предлагать идеи: от простых до самых амбициозных.</p> </li> </ul> <p>И всё это в комфортных условиях без бюрократии, дресс-кода и начальников.</p>',
 'branded_description': '\n<style>\n.tmpl_hh_wrapper p,\n.tmpl_hh_wrapper a,\n.tmpl_hh_wrapper img,\n.tmpl_hh_wrapper ol,\n.tmpl_hh_wrapper ul,\n.tmpl_hh_wrapper li {\n    margin: 0;\n    padding: 0;\n    border: 0;\n    font-size: 100%;\n    font: inherit;\n    vertical-align: baseline;\n}\n\n.hht-vacancydescription {\n    padding: 0px;\n}\n\n.tmpl_hh_wrapper .l-cell,\n.tmpl_hh_wrapper .l-paddings {\n    padding: 0px !important;\n}\n\n.tmpl_hh_wrapper .b-vacancy-desc-wrapper {\n    margin-top: 0px !important;    \n}\n\n.tmpl_hh_wrapper .b-vacancy-desc {\n    overflow: visible !important;\n    line-height: inherit;\n}\n\n.tmpl_hh_content ol li b,\n.tmpl_hh_content ol li strong,\n.tmpl_hh_content ol li p b,\n.tmpl_hh_content ol li p strong,\n.tmpl_hh_content ul li b,\n.tmpl_hh_content ul li strong,\n.tmpl_hh_content ul li p b,\n.tmpl_hh_content ul li p strong {\n    font-weight: normal;\n    font-size: inherit !important;\n    color: inherit !important;\n    margin: 0 !important;\n    text-transform: none;\n    line-height: inherit;\n}\n\n.tmpl_hh_content ol li p,\n.tmpl_hh_content ul li p {\n    font-weight: normal;\n    margin: 0;\n}\n\n.tmpl_hh_content p b,\n.tmpl_hh_content p strong {\n    margin: 0 0 0;\n    padding: 28px 0 8px;\n}\n\n.tmpl_hh_wrapper {\n    width: 100%;\n    margin: 0 auto;\n    max-width: 690px;\n    position: relative;\n    word-break: normal;\n    color: #333333;\n    overflow: hidden;\n    font-family: \'Verdana\', sans-serif;\n    font-size: 14px;\n    line-height: 20px;\n    -webkit-font-smoothing: antialiased;\n}\n\n.tmpl_hh_wrapper img {\n    width: 100%;\n    display: block;\n}\n\n.tmpl_hh_content {\n    padding: 41px 40px 34px;\n    position: relative;\n    z-index: 1;\n}\n\n.tmpl_hh_content p:first-child,\n.tmpl_hh_content>strong:first-child,\n.tmpl_hh_content div>strong:first-child {\n    margin-top: 0 !important;\n}\n\n.tmpl_hh_content p,\n.tmpl_hh_content b,\n.tmpl_hh_content strong {\n   margin: 12px 0 12px;\n}\n\n.tmpl_hh_content b, \n.tmpl_hh_content strong {\n    display: inline-block;\n    font-weight: bold;\n    font-size: 24px;\n    line-height: 32px;\n}\n\n.tmpl_hh_content ol,\n.tmpl_hh_content ul {\n    margin-left: 15px;\n    list-style: none !important;\n}\n\n.tmpl_hh_content ol {\n    counter-reset: list_counter;\n}\n\n.tmpl_hh_content li {\n    position: relative;\n    margin-bottom: 12px;\n}\n\n.tmpl_hh_content ul ul,\n.tmpl_hh_content ul ol,\n.tmpl_hh_content ol ol,\n.tmpl_hh_content ol ul {\n    margin-top: 12px;\n}\n\n.tmpl_hh_content ol>li {\n    counter-increment: list_counter;    \n}\n\n.tmpl_hh_content li:before {\n    position: absolute;\n    left: -15px;\n    top: 0;\n}\n\n.tmpl_hh_content ul>li:before {\n    content: "";\n    height: 5px;\n    width: 5px;\n    background: #333333;\n    opacity: 0.45;\n    border-radius: 50%;\n    top: 7px;\n}\n\n.tmpl_hh_content ol>li:before {\n    content: counter(list_counter)\'.\';\n    left: auto;\n    right: 100%;\n    margin-right: 2px;\n}\n\n.tmpl_hh_header {\n    padding: 6.5% 40px 0;\n    background: url(https://hhcdn.ru/ichameleon/152526.png) 0 0 no-repeat;\n    background-size: 21% auto;\n}\n\n.tmpl_hh_header_logo {\n    position: relative;\n    width: 28.6%;\n}\n\n.tmpl_hh_footer {\n    position: relative;\n    background: url(https://hhcdn.ru/ichameleon/152638.jpg);\n    height: 0;\n    padding-bottom: 56.4%;\n    background-size: 100%;\n    background-repeat: no-repeat;\n}\n\np.tmpl_hh_foonote {\n    position: absolute;\n    bottom: 10px;\n    left: 4.6%;\n    font-size: 9px;\n    line-height: 9px;\n    z-index: 1;\n}\n\n@media (max-width: 699px) {\n    .tmpl_hh_content p b, .tmpl_hh_content p strong {\n        padding: 18px 0 3px;\n    }\n\n    .tmpl_hh_content b, .tmpl_hh_content strong {\n        font-size: 20px;\n        line-height: 28px;\n    }\n\n    .tmpl_hh_header {\n        padding: 12.9% 0 0% 0%;\n        background: url(https://hhcdn.ru/ichameleon/152842.png) 0 0 no-repeat;\n        background-size: 26% auto;\n    }\n\n    .tmpl_hh_header_logo {\n        width: 50.2%; \n    }\n\n    .tmpl_hh_content {\n        padding: 43px 0% 0px;\n    }\n\n    .tmpl_hh_footer {\n        background: url(https://hhcdn.ru/ichameleon/152640.jpg);\n        padding-bottom: 129.4%;\n        background-size: 106%;\n        background-repeat: no-repeat;\n        margin-top: -4%;\n    }\n\n    p.tmpl_hh_foonote {\n        position: relative;\n        top: 0;\n        left: 0;\n        margin-top: 2%;\n    }\n}\n</style>\n\n\n<div class="tmpl_hh_wrapper">\n        <div class="tmpl_hh_header">\n            <div class="tmpl_hh_header_logo"><img src="https://hhcdn.ru/ichameleon/152525.svg" alt=""></div>\n        </div>\n        <div class="tmpl_hh_content">\n            <p>Ищем специалиста по Data Science, чтобы строить и улучшать модели машинного обучения, которые помогут усовершенствовать наш продукт и внутренние процессы. Мы стремимся к тому, чтобы мы стали быстрее и удобнее для клиентов. И в этом нам нужна твоя помощь.</p> <p><strong>Что нужно делать</strong></p> <p>Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний по данным о бизнесе.</p> <p>Ты будешь доставать данные из баз и других источников, приводить их к нужному виду, анализировать и затем строить модели. Тебе предстоит планировать и ставить эксперименты, анализировать результаты и их статистическую значимость. Использовать feature engineering, model selection и fine tuning.</p> <p><strong>Ты подойдешь, если</strong></p> <ul> <li> <p>Знаешь Python, умеешь обрабатывать данные с помощью pandas, NumPy, Plotly.</p> </li> <li> <p>У тебя есть опыт работы с SQL.</p> </li> <li> <p>Есть опыт работы с методами машинного обучения и основными инструментами data science: Scikit-learn, XGBoost, CatBoost и т.п.</p> </li> <li> <p>Разбираешься в математической статистике, теории вероятностей и знаешь, как проводить A/B тестирования.</p> </li> </ul> <p><strong>Будет плюсом, если</strong></p> <ul> <li> <p>Ты понимаешь принципы работы нейросетей и уже имеешь опыт с одним или несколькими фреймворками для глубокого обучения: TensorFlow или PyTorch.</p> </li> <li> <p>Умеешь вводить модели машинного обучения в работу production.</p> </li> </ul> <p><strong>Что будет твоим в Точке</strong></p> <ul> <li> <p>Зарплата от 100 000 ₽. Расскажи на собеседовании, какая зарплата будет комфортной для тебя. А мы определим твой грейд по хард и софт скиллам и назовём точную сумму.</p> </li> <li> <p>Официальное трудоустройство и бесплатная страховка здоровья даже за границей.</p> </li> <li> <p>Удобный график: гибкое начало и окончание рабочего дня.</p> </li> <li> <p>Современный и уютный офис со спортзалом и библиотекой, кофе-поинтами, кухнями и зонами отдыха.</p> </li> <li> <p>Гибкие методы управления: мы используем Agile и SCRUM, чтобы каждый день создавать новое и быстро реагировать на изменения.</p> </li> <li> <p>Бесплатное корпоративное обучение: мы ездим на IT-конференции, собираемся на митапы, раздаем призы на хакатонах и проходим курсы за счёт компании.</p> </li> <li> <p>Возможность принимать решения без тысячи согласований и предлагать идеи: от простых до самых амбициозных.</p> </li> </ul> <p>И всё это в комфортных условиях без бюрократии, дресс-кода и начальников.</p></div>\n        <div class="tmpl_hh_footer"></div>\n        <p class="tmpl_hh_foonote">АО\xa0«Точка»</p>\n    </div>\n',
 'vacancy_constructor_template': None,
 'key_skills': [{'name': 'аналитика'},
  {'name': 'SQL'},
  {'name': 'Python'},
  {'name': 'Информационные технологии'},
  {'name': 'Работа с базами данных'},
  {'name': 'Математический анализ'},
  {'name': 'NumPy'},
  {'name': 'Математическая статистика'},
  {'name': 'XGBoost'}],
 'accept_handicapped': False,
 'accept_kids': False,
 'archived': False,
 'response_url': None,
 'specializations': [{'id': '17.751',
   'name': 'Другое',
   'profarea_id': '17',
   'profarea_name': 'Продажи'},
  {'id': '1.25',
   'name': 'Аналитик',
   'profarea_id': '1',
   'profarea_name': 'Информационные технологии, интернет, телеком'},
  {'id': '3.26',
   'name': 'Аналитик',
   'profarea_id': '3',
   'profarea_name': 'Маркетинг, реклама, PR'},
  {'id': '12.746',
   'name': 'Другое',
   'profarea_id': '12',
   'profarea_name': 'Консультирование'}],
 'professional_roles': [{'id': '10', 'name': 'Аналитик'}],
 'code': None,
 'hidden': False,
 'quick_responses_allowed': False,
 'driver_license_types': [],
 'accept_incomplete_resumes': False,
 'employer': {'id': '2324020',
  'name': 'Точка',
  'url': 'https://api.hh.ru/employers/2324020',
  'alternate_url': 'https://hh.ru/employer/2324020',
  'logo_urls': {'240': 'https://hhcdn.ru/employer-logo/3414734.jpeg',
   '90': 'https://hhcdn.ru/employer-logo/3414733.jpeg',
   'original': 'https://hhcdn.ru/employer-logo-original/743443.jpg'},
  'vacancies_url': 'https://api.hh.ru/vacancies?employer_id=2324020',
  'trusted': True},
 'published_at': '2022-03-17T12:37:57+0300',
 'created_at': '2022-03-17T12:37:57+0300',
 'negotiations_url': None,
 'suitable_resumes_url': None,
 'apply_alternate_url': 'https://hh.ru/applicant/vacancy_response?vacancyId=49423067',
 'has_test': False,
 'test': None,
 'alternate_url': 'https://hh.ru/vacancy/49423067',
 'working_days': [],
 'working_time_intervals': [],
 'working_time_modes': [],
 'accept_temporary': False}

Задача 1.¶

Исследуем профессию Data Scientist. Найдите как можно больше вакансий по этой профессии в Москве. Учтите, что имеет смысл искать также по другим ключевым словам, например аналитик данных.

In [ ]:
parametrs_for_text = ["Data Science", "Аналитик Данных", "Data Analyst", "Data Scientist"]

all_vacancies = pd.DataFrame([])

for i in range(0, 2):
    j = 0
    while True:
        params = {
            'text': parametrs_for_text[2 * i] + " OR " + parametrs_for_text[2 * i + 1],
            'area': 1,
            'page': j,
            'per_page': 100
        }
        req = requests.get(URL, params)
        data = json.loads(req.content.decode())
        if not 'items' in data.keys():
            break
        j += 1
        all_vacancies = pd.concat([pd.json_normalize(data['items']), all_vacancies], ignore_index=True)
        sleep(0.5)
In [ ]:
all_vacancies
Out[ ]:
id premium name has_test response_letter_required salary response_url sort_point_distance published_at created_at ... department salary.from salary.to salary.currency salary.gross address address.metro employer.logo_urls insider_interview.id insider_interview.url
0 54029828 False Middle / Senior Java Developer (SberDevices) False False NaN None None 2022-03-18T09:40:22+0300 2022-03-18T09:40:22+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 50332932 False Middle android-разработчик False False NaN None None 2022-03-15T11:45:41+0300 2022-03-15T11:45:41+0300 ... NaN 200000.0 NaN RUR False NaN NaN NaN NaN NaN
2 50673248 False SEO специалист (Senior / Lead) False False NaN None None 2022-02-28T14:29:34+0300 2022-02-28T14:29:34+0300 ... NaN 130000.0 NaN RUR False NaN NaN NaN NaN NaN
3 52899274 False Senior iOS-разработчик в команду мобильного пр... False False NaN None None 2022-03-18T13:49:51+0300 2022-03-18T13:49:51+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 53218197 False Ведущий менеджер по маркетингу (VK) False False NaN None None 2022-03-01T22:33:31+0300 2022-03-01T22:33:31+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3655 53171872 False Quantitative Trader / Quantitative Analyst False False NaN None None 2022-03-18T14:09:03+0300 2022-03-18T14:09:03+0300 ... NaN 3500.0 NaN USD False NaN NaN NaN NaN NaN
3656 53169751 False Младший консультант/бизнес-аналитик False False NaN None None 2022-03-18T13:33:05+0300 2022-03-18T13:33:05+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3657 53804412 False Аналитик False False NaN None None 2022-03-17T10:43:44+0300 2022-03-17T10:43:44+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3658 53150521 False Старший аналитик НСМ False False NaN None None 2022-03-18T09:06:53+0300 2022-03-18T09:06:53+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3659 51710996 False Аналитик товарной категории False False NaN None None 2022-03-18T09:06:20+0300 2022-03-18T09:06:20+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

3660 rows × 66 columns

В полученную выборку некоторые вакансии могли попасть несколько раз. Удалите дубликаты.

In [ ]:
all_vacancies.drop_duplicates(subset=['id'], ignore_index=True, inplace = True)
all_vacancies
Out[ ]:
id premium name has_test response_letter_required salary response_url sort_point_distance published_at created_at ... department salary.from salary.to salary.currency salary.gross address address.metro employer.logo_urls insider_interview.id insider_interview.url
0 54029828 False Middle / Senior Java Developer (SberDevices) False False NaN None None 2022-03-18T09:40:22+0300 2022-03-18T09:40:22+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 50332932 False Middle android-разработчик False False NaN None None 2022-03-15T11:45:41+0300 2022-03-15T11:45:41+0300 ... NaN 200000.0 NaN RUR False NaN NaN NaN NaN NaN
2 50673248 False SEO специалист (Senior / Lead) False False NaN None None 2022-02-28T14:29:34+0300 2022-02-28T14:29:34+0300 ... NaN 130000.0 NaN RUR False NaN NaN NaN NaN NaN
3 52899274 False Senior iOS-разработчик в команду мобильного пр... False False NaN None None 2022-03-18T13:49:51+0300 2022-03-18T13:49:51+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 53218197 False Ведущий менеджер по маркетингу (VK) False False NaN None None 2022-03-01T22:33:31+0300 2022-03-01T22:33:31+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3293 53171872 False Quantitative Trader / Quantitative Analyst False False NaN None None 2022-03-18T14:09:03+0300 2022-03-18T14:09:03+0300 ... NaN 3500.0 NaN USD False NaN NaN NaN NaN NaN
3294 53169751 False Младший консультант/бизнес-аналитик False False NaN None None 2022-03-18T13:33:05+0300 2022-03-18T13:33:05+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3295 53804412 False Аналитик False False NaN None None 2022-03-17T10:43:44+0300 2022-03-17T10:43:44+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3296 53150521 False Старший аналитик НСМ False False NaN None None 2022-03-18T09:06:53+0300 2022-03-18T09:06:53+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3297 51710996 False Аналитик товарной категории False False NaN None None 2022-03-18T09:06:20+0300 2022-03-18T09:06:20+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

3298 rows × 66 columns

Загрузите подробное описание каждой вакансии и создайте удобную таблицу данных.

In [ ]:
final_table = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
In [ ]:
for i in tqdm(all_vacancies.index):
    tmp_line = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
    
    vacancy = all_vacancies['id'].iloc[i]
    vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'
    req = requests.get(vacancy_url)
    vacancy_info = json.loads(req.content.decode())
    df_vacancy = pd.json_normalize(vacancy_info)
    
    tmp_line[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']] = df_vacancy[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']]
                                                                          
    if 'salary.from' in df_vacancy.columns:
        tmp_line[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']] = df_vacancy[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
    tmp_line[['employer.name', 'lat', 'lng']] = all_vacancies[['employer.name', 'address.lat', 'address.lng']].iloc[i]
    final_table = pd.concat([final_table, tmp_line], ignore_index=True)
    sleep(0.5)
100%|███████████████████████████████████████████████████████████| 3298/3298 [41:43<00:00,  1.32it/s]
In [ ]:
final_table['key_skills'] = list(map(lambda x: [y['name'] for y in x], final_table['key_skills']))
final_table[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']] = all_vacancies[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']]
final_table
Out[ ]:
id employer.name name key_skills schedule.name description salary.from salary.to salary.currency salary.gross lat lng experience.name address.metro.station_name address.metro.line_name address.metro.lat address.metro.lng
0 54029828 Сбербанк Middle / Senior Java Developer (SberDevices) [Java, Kotlin, Spring] Полный день <p>Приглашаем в нашу команду специалистов, кот... NaN NaN NaN NaN 55.741338 37.531127 От 3 до 6 лет Кутузовская Филевская 55.740544 37.534100
1 50332932 Константа Middle android-разработчик [MVP, RxJava, Room, Kotlin, MVVM] Гибкий график <p>Привет! Мы в Константе создаем различные пр... 200000 NaN RUR False 55.785068 37.655580 От 1 года до 3 лет Красносельская Сокольническая 55.780014 37.666097
2 50673248 ВБЦ SEO специалист (Senior / Lead) [SEO, Продвижение сайтов, JS, Java Script, Раб... Полный день <p><strong>Группа компаний «ВБЦ» – российская ... 130000 NaN RUR False 55.751832 37.525270 От 1 года до 3 лет Тестовская МЦД - 1 55.754292 37.531551
3 52899274 Туту.ру Senior iOS-разработчик в команду мобильного пр... [Git, Swift, iOS, Adobe Photoshop, Sketch] Полный день <p>Наш ключевой продукт — это единое приложени... NaN NaN NaN NaN 55.678458 37.632287 От 1 года до 3 лет Нагатинская Серпуховско-Тимирязевская 55.682099 37.620917
4 53218197 VK Ведущий менеджер по маркетингу (VK) [Google Analytics, Яндекс.Метрика, Работа с бо... Удаленная работа <p>Мы являемся частью экосистемы VK и занимаем... NaN NaN NaN NaN NaN NaN От 3 до 6 лет NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3293 53171872 Alber Blanc Quantitative Trader / Quantitative Analyst [Python, C/C++, Математическая статистика, Ана... Гибкий график <p><strong>Мы, в Alber Blanc, занимаемся высок... 3500 None USD False NaN NaN От 1 года до 3 лет NaN NaN NaN NaN
3294 53169751 Т1 Консалтинг Младший консультант/бизнес-аналитик [Английский язык, MS PowerPoint, Подготовка пр... Полный день <p><strong>Т1 Консалтинг – </strong>российская... NaN None NaN NaN 55.708354 37.652705 От 1 года до 3 лет Автозаводская Замоскворецкая 55.706634 37.657008
3295 53804412 ДИАМЕД-ФАРМА Аналитик [] Полный день <p><strong>«ДИАМЕД - фарма» </strong>- совреме... NaN None NaN NaN 55.840245 37.492024 От 3 до 6 лет NaN NaN NaN NaN
3296 53150521 ИНТЕР РАО ИТ Старший аналитик НСМ [Обучение и развитие, Управление проектами, At... Полный день <p>Приглашаем на работу в ИТ-компанию, входящу... NaN None NaN NaN 55.730152 37.567815 От 3 до 6 лет Спортивная Сокольническая 55.722388 37.562041
3297 51710996 O'STIN Аналитик товарной категории [] Полный день <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... NaN None NaN NaN 55.792589 37.527588 От 1 года до 3 лет Аэропорт Замоскворецкая 55.800441 37.530477

3298 rows × 17 columns

In [ ]:
final_table.to_excel("vacancy_description.xlsx")
In [ ]:
all_vacancies.to_excel("all_vacancies.xlsx")

Полученную таблицу необходимо сохранить в формате xlsx и отправить боту вместе с решением.

Вопрос 1. Сколько сейчас доступно вакансий по вашему запросу?

In [ ]:
final_table.shape[0]
Out[ ]:
3298

Вопрос 2. Какие навыки чаще всего встречаются в вакансиях по данной специальности?

Для этого найдите соответствующее поле в данных, проанализируйте его и составьте список навыков и количество упоминаний каждого. Визуализируйте полученную информацию по топ-15 навыков.

In [ ]:
table_skills = {}

for skills in final_table["key_skills"]:
    for skill in skills:
        if table_skills.get(skill) == None:
            table_skills[skill] = 1
            continue
        table_skills[skill] += 1
        
df_skills = pd.DataFrame.from_dict(table_skills, orient='index').reset_index().rename(columns={'index' : 'навыки', 0 : 'кол-во'}).sort_values(by='кол-во', ascending = False)
In [ ]:
df_skills.head(15)
Out[ ]:
навыки кол-во
29 SQL 1130
71 Python 756
101 Английский язык 493
36 Анализ данных 415
61 Аналитическое мышление 411
81 MS PowerPoint 406
75 Управление проектами 232
28 Работа с большим объемом информации 206
30 PostgreSQL 192
85 MS SQL 186
82 Бизнес-анализ 179
21 Git 176
132 MS Excel 169
137 Tableau 167
212 Data Analysis 163
In [ ]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(15, 10))
    sns.barplot(y="навыки", x="кол-во", data=df_skills.head(15));
    plt.title("Топ-15 навыков для Аналитика Данных", fontweight = "bold", fontsize = 19)

По топ навыкам мы можем сказать, что наш запрос был успешным. Ведь для аналитика данных и вправду необходимы выше описанные навыки. Как мы видим компании больше всего требуют знания SQL, Python, Английский язык и Анализ данных.

Вопрос 3. Какую зарплату готовы платить работодатели? Соберите некоторым образом статистику и постройте гистограмму.

При работе с данными о заработной плате обратите внимание на валюту и gross/net.

In [ ]:
df_salary = final_table[(final_table['salary.from'] == final_table['salary.from']) | (final_table['salary.to'] == final_table['salary.to'])]
df_salary = df_salary[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
df_salary
Out[ ]:
salary.from salary.to salary.currency salary.gross
1 200000 None RUR False
2 130000 None RUR False
6 180 230000 RUR False
22 200000 250000 RUR False
28 None 6000 USD True
... ... ... ... ...
3281 120000 260000 RUR False
3282 250000 300000 RUR False
3286 80000 None RUR True
3288 80000 None RUR True
3293 3500 None USD False

895 rows × 4 columns

In [ ]:
mean_salary = []
for i in df_salary.index:
    sal = 0
    if df_salary['salary.from'][i] == None:
        sal = df_salary['salary.to'][i]
    elif df_salary['salary.to'][i] == None:
        sal = df_salary['salary.from'][i]
    else:
        sal = (df_salary['salary.from'][i] + df_salary['salary.to'][i]) / 2
    
    if df_salary['salary.currency'][i] == 'USD':
        sal *= 111
    elif df_salary['salary.currency'][i] == 'EUR':
        sal *= 122
        
    if df_salary['salary.gross'][i] == True:
        sal *= 0.87
        
    mean_salary.append(sal)
In [ ]:
df_salary["salary.mean"] = mean_salary
df_salary
Out[ ]:
salary.from salary.to salary.currency salary.gross salary.mean
1 200000 None RUR False 200000.0
2 130000 None RUR False 130000.0
6 180 230000 RUR False 115090.0
22 200000 250000 RUR False 225000.0
28 None 6000 USD True 579420.0
... ... ... ... ... ...
3281 120000 260000 RUR False 190000.0
3282 250000 300000 RUR False 275000.0
3286 80000 None RUR True 69600.0
3288 80000 None RUR True 69600.0
3293 3500 None USD False 388500.0

895 rows × 5 columns

In [ ]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(13, 8))
    plt.xlim((0, 0.7 * 10**6))
    sns.histplot(data=df_salary['salary.mean'], alpha = 0.8)
    plt.ylabel("кол-во работодателей")
    plt.xlabel("зарплата")
    plt.title("Кол-во вакансий в области Data Science разных зарплат\n", fontweight = "bold", fontsize = 19)

По гистограмме видно, что средняя зарплата Аналитика данных $90000$ - $150000$. Также многие работодатели готовы платить от $200000$ до $300000$, что не может нас не радовать.

Проанализируем для инвестиционного аналитика¶

In [3]:
parametrs_for_text = ['Венчурный капитал', 'Финансовый аналитик', 'Инвестиционный аналитик', 'Венчурный инвестор']

all_vacancies_ml = pd.DataFrame([])

for i in range(0, 2):
    j = 0
    while True:
        params = {
            'text': parametrs_for_text[2 * i] + " OR " + parametrs_for_text[2 * i + 1],
            'area': 1,
            'page': j,
            'per_page': 100
        }
        req = requests.get(URL, params)
        data = json.loads(req.content.decode())
        if not 'items' in data.keys():
            break
        j += 1
        all_vacancies_ml = pd.concat([pd.json_normalize(data['items']), all_vacancies_ml], ignore_index=True)
        sleep(0.5)
In [4]:
all_vacancies_ml.drop_duplicates(subset=['id'], ignore_index=True, inplace = True)
all_vacancies_ml
Out[4]:
id premium name department has_test response_letter_required address response_url sort_point_distance published_at ... address.metro.lng address.metro_stations address.id address.metro employer.logo_urls department.id department.name insider_interview.id insider_interview.url immediate_redirect_url
0 53265736 False Инвестиционный аналитик (сейлз) NaN False False NaN None None 2022-03-02T12:01:25+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 51783161 False Инвестиционный аналитик/Инвестиционный менеджер NaN False False NaN None None 2022-02-25T09:40:02+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 52023549 False Консультант / инвестиционный аналитик NaN False False NaN None None 2022-03-14T14:22:05+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 51773289 False Инвестиционный аналитик (финансовое моделирова... NaN False False NaN None None 2022-03-15T11:46:15+0300 ... 37.562271 [{'station_name': 'Улица 1905 года', 'line_nam... 2919650 NaN NaN NaN NaN NaN NaN NaN
4 50342220 False Младший инвестиционный аналитик/оценщик (недви... NaN False False NaN None None 2022-03-15T11:17:14+0300 ... NaN [] 3531439 NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1546 48266162 False Главный экономист (Методология и управление из... NaN False False NaN None None 2022-03-15T13:04:16+0300 ... 37.680726 [{'station_name': 'Площадь Ильича', 'line_name... 1446 NaN NaN NaN NaN NaN NaN NaN
1547 53687844 False Руководитель направления "Финансовый анализ" NaN False False NaN None None 2022-03-11T13:14:33+0300 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1548 54036890 False Младший финансовый менеджер/Аналитик NaN False False NaN None None 2022-03-18T11:35:20+0300 ... NaN [] 3817280 NaN NaN NaN NaN NaN NaN NaN
1549 53548751 False Финансовый аналитик (Food / Nonfood) NaN False False NaN None None 2022-03-09T09:35:03+0300 ... NaN [] 643651 NaN NaN NaN NaN NaN NaN NaN
1550 53369065 False Финансовый аналитик NaN False False NaN None None 2022-03-04T12:34:41+0300 ... NaN [] 3692511 NaN NaN NaN NaN NaN NaN NaN

1551 rows × 67 columns

In [5]:
final_table_ml = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
In [6]:
for i in tqdm(all_vacancies_ml.index):
    tmp_line = pd.DataFrame([], columns = ['id','employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
    
    vacancy = all_vacancies_ml['id'].iloc[i]
    vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'
    req = requests.get(vacancy_url)
    vacancy_info = json.loads(req.content.decode())
    df_vacancy = pd.json_normalize(vacancy_info)
    
    tmp_line[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']] = df_vacancy[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']]
                                                                          
    if 'salary.from' in df_vacancy.columns:
        tmp_line[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']] = df_vacancy[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
    tmp_line[['lat', 'lng', 'employer.name']] = all_vacancies_ml[['address.lat', 'address.lng', 'employer.name']].iloc[i]
    final_table_ml = pd.concat([final_table_ml, tmp_line], ignore_index=True)
    sleep(0.5)
100%|███████████████████████████████████████████████████████████| 1551/1551 [17:43<00:00,  1.46it/s]
In [7]:
final_table_ml['key_skills'] = list(map(lambda x: [y['name'] for y in x], final_table_ml['key_skills']))
final_table_ml[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']] = all_vacancies_ml[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']]
final_table_ml
Out[7]:
id employer.name name key_skills schedule.name description salary.from salary.to salary.currency salary.gross lat lng experience.name address.metro.station_name address.metro.line_name address.metro.lat address.metro.lng
0 53265736 Cornerstone Russia Инвестиционный аналитик (сейлз) [Активные продажи, работа с VIP клиентами, Фон... Гибкий график <p>Крупный российский банк (ТОП 20 самых надеж... None 250000 RUR True NaN NaN От 1 года до 3 лет NaN NaN NaN NaN
1 51783161 Скайлав Рус Инвестиционный аналитик/Инвестиционный менеджер [Английский язык, Анализ инвестиционных проект... Полный день <strong>Обязанности:</strong> <ul> <li> <p>Соз... None NaN NaN NaN NaN NaN Нет опыта NaN NaN NaN NaN
2 52023549 КБ Стрелка Консультант / инвестиционный аналитик [Английский язык, Управление проектами, Ведени... Полный день <p>КБ Стрелка — ведущий консультант в области ... None NaN NaN NaN NaN NaN От 1 года до 3 лет NaN NaN NaN NaN
3 51773289 АПХ ЭКО-культура Инвестиционный аналитик (финансовое моделирова... [Финансовый анализ, Анализ инвестиционных прое... Полный день <p>Агропромышленный холдинг <strong>«ЭКО-культ... None NaN NaN NaN 55.754968 37.509262 Нет опыта Улица 1905 года Таганско-Краснопресненская 55.763944 37.562271
4 50342220 Sminex Младший инвестиционный аналитик/оценщик (недви... [] Полный день <p><strong>Sminex</strong></p> <p>Приоритетная... None NaN NaN NaN 55.742706 37.617734 Нет опыта NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1546 48266162 Промсвязьбанк Главный экономист (Методология и управление из... [] Полный день <p><strong>Ключевые задачи:</strong></p> <ul> ... NaN NaN NaN NaN 55.735876 37.710896 От 1 года до 3 лет Площадь Ильича Калининская 55.747115 37.680726
1547 53687844 Х5 Group Руководитель направления "Финансовый анализ" [Работа в команде, Деловая коммуникация, Управ... Полный день <strong>Обязанности:</strong> <ul> <li>Выполне... NaN NaN NaN NaN NaN NaN От 3 до 6 лет NaN NaN NaN NaN
1548 54036890 Центр Орбита Младший финансовый менеджер/Аналитик [Финансовый анализ, Бюджетирование, Бухгалтерс... Полный день <p><strong>Группа компаний Орбита - партнер ве... None 120000 RUR True 55.748143 37.540488 От 3 до 6 лет NaN NaN NaN NaN
1549 53548751 Р-Фарм Финансовый аналитик (Food / Nonfood) [BPMN, Финансовый контроль, Финансовый контрол... Полный день <p><strong>Задачи:</strong></p> <p>Импорт и оп... NaN NaN NaN NaN 55.775869 37.612057 От 3 до 6 лет NaN NaN NaN NaN
1550 53369065 Центр хранения и анализа больших данных Финансовый аналитик [Финансовый анализ, Анализ инвестиционных прое... Полный день <p>Вакансия для тех, кто хочет научиться привл... 70000 100000 RUR False 55.696514 37.526483 От 1 года до 3 лет NaN NaN NaN NaN

1551 rows × 17 columns

In [8]:
final_table_ml.to_excel("vacancy_description_ml.xlsx")

Сколько сейчас доступно вакансий по вашему запросу?

In [9]:
final_table_ml.shape[0]
Out[9]:
1551

Какие навыки чаще всего встречаются в вакансиях по данной специальности?

Для этого найдите соответствующее поле в данных, проанализируйте его и составьте список навыков и количество упоминаний каждого. Визуализируйте полученную информацию по топ-15 навыков.

In [10]:
table_skills_ml = {}

for skills in final_table_ml["key_skills"]:
    for skill in skills:
        if table_skills_ml.get(skill) == None:
            table_skills_ml[skill] = 1
            continue
        table_skills_ml[skill] += 1
        
df_skills_ml = pd.DataFrame.from_dict(table_skills_ml, orient='index').reset_index().rename(columns={'index' : 'навыки', 0 : 'кол-во'}).sort_values(by='кол-во', ascending = False)
In [11]:
df_skills_ml.head(15)
Out[11]:
навыки кол-во
13 Финансовый анализ 754
49 Управленческая отчетность 321
9 MS PowerPoint 313
113 Финансовая отчетность 309
381 Бюджетирование 295
5 Английский язык 250
421 Финансовый контроль 235
18 Анализ финансовых показателей 160
112 Аналитическое мышление 150
161 MS Excel 142
7 Финансовое моделирование 137
209 Финансовое планирование 126
29 Экономический анализ 126
15 Анализ текущих финансовых показателей 125
38 Работа с большим объемом информации 124
In [12]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(15, 10))
    sns.barplot(y="навыки", x="кол-во", data=df_skills_ml.head(15));
    plt.title("Топ-15 навыков для Инвестиционного Аналитика", fontweight = "bold", fontsize = 19)

Тут мы можем сказать, что от инвестиционного аналитика больше всего требуют знания Финансового анализа, Управленческая отчетность, MS PowerPoint и Финансовая отчетность.

In [13]:
df_salary_ml = final_table_ml[(final_table_ml['salary.from'] == final_table_ml['salary.from']) | (final_table_ml['salary.to'] == final_table_ml['salary.to'])]
df_salary_ml = df_salary_ml[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
df_salary_ml
Out[13]:
salary.from salary.to salary.currency salary.gross
0 None 250000 RUR True
5 None 2500 EUR True
8 60000 80000 RUR False
16 None 6600 EUR False
25 100000 120000 RUR True
... ... ... ... ...
1538 90000 115000 RUR True
1543 100000 None RUR False
1544 100000 300000 RUR True
1548 None 120000 RUR True
1550 70000 100000 RUR False

512 rows × 4 columns

In [14]:
mean_salary_ml = []
for i in df_salary_ml.index:
    sal = 0
    if df_salary_ml['salary.from'][i] == None:
        sal = df_salary_ml['salary.to'][i]
    elif df_salary_ml['salary.to'][i] == None:
        sal = df_salary_ml['salary.from'][i]
    else:
        sal = (df_salary_ml['salary.from'][i] + df_salary_ml['salary.to'][i]) / 2
    
    if df_salary_ml['salary.currency'][i] == 'USD':
        sal *= 111
    elif df_salary_ml['salary.currency'][i] == 'EUR':
        sal *= 122
        
    if df_salary_ml['salary.gross'][i] == True:
        sal *= 0.87
        
    mean_salary_ml.append(sal)
In [15]:
df_salary_ml["salary.mean"] = mean_salary_ml
df_salary_ml
Out[15]:
salary.from salary.to salary.currency salary.gross salary.mean
0 None 250000 RUR True 217500.0
5 None 2500 EUR True 265350.0
8 60000 80000 RUR False 70000.0
16 None 6600 EUR False 805200.0
25 100000 120000 RUR True 95700.0
... ... ... ... ... ...
1538 90000 115000 RUR True 89175.0
1543 100000 None RUR False 100000.0
1544 100000 300000 RUR True 174000.0
1548 None 120000 RUR True 104400.0
1550 70000 100000 RUR False 85000.0

512 rows × 5 columns

In [16]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(13, 8))
    plt.xlim((0, 0.4 * 10**6))
    sns.histplot(data=df_salary_ml['salary.mean'], alpha = 0.8)
    plt.ylabel("кол-во работодателей")
    plt.xlabel("средняя зарплата")
    plt.title("Кол-во вакансий в области инвестиционного анализа разных зарплат\n", fontweight = "bold", fontsize = 19)

По данной гистограмме сразу можно сказать, что средняя зарплата $90000$ - $100000$. Тут видно, что мало работодателей готовы платить выше $150000$.

Вывод: 1) Отдельно выводы по каждой профессии написаны под каждым графиком.

2) Теперь давайте сравним результаты анализа профессии "Аналитик данных" и "Инвестиционный аналитик":

  а) Кол-во вакансий на аналитика данных намного больше, чем на инвестиционного аналитика. Это показывает, что сейчас огромный спроси на аналитиков данных.
  б) Средняя зарплата аналитиков данных больше, чем у инвестиционного аналитика. Высокая зарплата у инвестиционного аналитика встречается реже, чем у аналитика данных. Это может быть связано с тем, что аналитиков данных меньше на рынке услуг, чем инвестиционных аналитиков + проффесия современная, новая, мало хороших специалистов, профессионалов.

Задача 2.¶

Для одной из рассмотренных ранее профессий ответьте на следующие вопросы:

  • Какой опыт требуется для данной вакансии?
  • Какие работодатели в топе?
  • В каком районе Москвы данная вакансия пользуется наибольшим и наименьшим спросом?

Не забудьте про визуализацию, для этого используйте библиотеку plotly. В частности, постройте распределений вакансий на карте.

Для построения последних двух графиков вам могут понадобиться внешние данные.

In [2]:
df = pd.read_excel('vacancy_description.xlsx')
df.drop(columns = ['Unnamed: 0'], inplace=True)
df
Out[2]:
id employer.name name key_skills schedule.name description salary.from salary.to salary.currency salary.gross lat lng experience.name address.metro.station_name address.metro.line_name address.metro.lat address.metro.lng
0 54029828 Сбербанк Middle / Senior Java Developer (SberDevices) ['Java', 'Kotlin', 'Spring'] Полный день <p>Приглашаем в нашу команду специалистов, кот... NaN NaN NaN NaN 55.741338 37.531127 От 3 до 6 лет Кутузовская Филевская 55.740544 37.534100
1 50332932 Константа Middle android-разработчик ['MVP', 'RxJava', 'Room', 'Kotlin', 'MVVM'] Гибкий график <p>Привет! Мы в Константе создаем различные пр... 200000.0 NaN RUR 0.0 55.785068 37.655580 От 1 года до 3 лет Красносельская Сокольническая 55.780014 37.666097
2 50673248 ВБЦ SEO специалист (Senior / Lead) ['SEO', 'Продвижение сайтов', 'JS', 'Java Scri... Полный день <p><strong>Группа компаний «ВБЦ» – российская ... 130000.0 NaN RUR 0.0 55.751832 37.525270 От 1 года до 3 лет Тестовская МЦД - 1 55.754292 37.531551
3 52899274 Туту.ру Senior iOS-разработчик в команду мобильного пр... ['Git', 'Swift', 'iOS', 'Adobe Photoshop', 'Sk... Полный день <p>Наш ключевой продукт — это единое приложени... NaN NaN NaN NaN 55.678458 37.632287 От 1 года до 3 лет Нагатинская Серпуховско-Тимирязевская 55.682099 37.620917
4 53218197 VK Ведущий менеджер по маркетингу (VK) ['Google Analytics', 'Яндекс.Метрика', 'Работа... Удаленная работа <p>Мы являемся частью экосистемы VK и занимаем... NaN NaN NaN NaN NaN NaN От 3 до 6 лет NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3293 53171872 Alber Blanc Quantitative Trader / Quantitative Analyst ['Python', 'C/C++', 'Математическая статистика... Гибкий график <p><strong>Мы, в Alber Blanc, занимаемся высок... 3500.0 NaN USD 0.0 NaN NaN От 1 года до 3 лет NaN NaN NaN NaN
3294 53169751 Т1 Консалтинг Младший консультант/бизнес-аналитик ['Английский язык', 'MS PowerPoint', 'Подготов... Полный день <p><strong>Т1 Консалтинг – </strong>российская... NaN NaN NaN NaN 55.708354 37.652705 От 1 года до 3 лет Автозаводская Замоскворецкая 55.706634 37.657008
3295 53804412 ДИАМЕД-ФАРМА Аналитик [] Полный день <p><strong>«ДИАМЕД - фарма» </strong>- совреме... NaN NaN NaN NaN 55.840245 37.492024 От 3 до 6 лет NaN NaN NaN NaN
3296 53150521 ИНТЕР РАО ИТ Старший аналитик НСМ ['Обучение и развитие', 'Управление проектами'... Полный день <p>Приглашаем на работу в ИТ-компанию, входящу... NaN NaN NaN NaN 55.730152 37.567815 От 3 до 6 лет Спортивная Сокольническая 55.722388 37.562041
3297 51710996 O'STIN Аналитик товарной категории [] Полный день <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... NaN NaN NaN NaN 55.792589 37.527588 От 1 года до 3 лет Аэропорт Замоскворецкая 55.800441 37.530477

3298 rows × 17 columns

Для начала поймем, какой опыт требуют от Аналитика Данных наши работодатели.

In [3]:
df['experience.name'].unique()
Out[3]:
array(['От 3 до 6 лет', 'От 1 года до 3 лет', 'Более 6 лет', 'Нет опыта'],
      dtype=object)
In [4]:
min_experience = list(map(lambda x: int(x[3]) if x[:2] == 'От' else (0 if x == 'Нет опыта' else 6), df['experience.name']))
In [5]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(13, 8))
    sns.histplot(data=min_experience, alpha = 0.8, discrete = True)
    plt.ylabel("кол-во работодателей")
    plt.xlabel("минимальный опыт")
    plt.title("Зависимость кол-ва работодателей от требуемого минимального опыта\n", fontweight = "bold", fontsize = 19)

Теперь построим топ работодателей по числу вакансий.

In [6]:
top_company = df.groupby(by = ['employer.name']).count().reset_index().rename(columns = {'id' : 'vacancy_count'})[['employer.name', 'vacancy_count']].sort_values(by='vacancy_count', ascending = False)
top_company                                                                   
Out[6]:
employer.name vacancy_count
1330 Сбербанк 113
912 Иннотех, Группа компаний 42
1401 Тинькофф 36
1570 билайн 36
1035 МТС 36
... ... ...
646 Ананьева Оксана Васильевна 1
645 Аналитическое кредитное рейтинговое агентство ... 1
643 Аналитические решения 1
642 Аналитическая компания АРЭНСИ Фарма 1
1573 ​​​​​​Мы занимаемся развитием и разработкой ра... 1

1574 rows × 2 columns

In [7]:
with sns.axes_style('whitegrid'):
    plt.figure(figsize=(15, 10))
    sns.barplot(y="employer.name", x="vacancy_count", data=top_company.head(15));
    plt.title("Топ работодателей по числу вакансий", fontweight = "bold", fontsize = 19)
    plt.ylabel('компании')
    plt.xlabel('число вакансий')
In [8]:
df_new = df.dropna(subset=['address.metro.line_name'])
df_new
Out[8]:
id employer.name name key_skills schedule.name description salary.from salary.to salary.currency salary.gross lat lng experience.name address.metro.station_name address.metro.line_name address.metro.lat address.metro.lng
0 54029828 Сбербанк Middle / Senior Java Developer (SberDevices) ['Java', 'Kotlin', 'Spring'] Полный день <p>Приглашаем в нашу команду специалистов, кот... NaN NaN NaN NaN 55.741338 37.531127 От 3 до 6 лет Кутузовская Филевская 55.740544 37.534100
1 50332932 Константа Middle android-разработчик ['MVP', 'RxJava', 'Room', 'Kotlin', 'MVVM'] Гибкий график <p>Привет! Мы в Константе создаем различные пр... 200000.0 NaN RUR 0.0 55.785068 37.655580 От 1 года до 3 лет Красносельская Сокольническая 55.780014 37.666097
2 50673248 ВБЦ SEO специалист (Senior / Lead) ['SEO', 'Продвижение сайтов', 'JS', 'Java Scri... Полный день <p><strong>Группа компаний «ВБЦ» – российская ... 130000.0 NaN RUR 0.0 55.751832 37.525270 От 1 года до 3 лет Тестовская МЦД - 1 55.754292 37.531551
3 52899274 Туту.ру Senior iOS-разработчик в команду мобильного пр... ['Git', 'Swift', 'iOS', 'Adobe Photoshop', 'Sk... Полный день <p>Наш ключевой продукт — это единое приложени... NaN NaN NaN NaN 55.678458 37.632287 От 1 года до 3 лет Нагатинская Серпуховско-Тимирязевская 55.682099 37.620917
8 48175455 Ренессанс Кредит Руководитель группы разработки ДБО [] Полный день <p><strong>IT</strong><strong>-команда «Ренесс... NaN NaN NaN NaN 55.796273 37.599687 От 3 до 6 лет Савёловская Серпуховско-Тимирязевская 55.794054 37.587163
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3284 53995806 SberTech Аналитик ['UML', 'BPMN', 'IDEF', 'MS Visio', 'Моделиров... Полный день <p>Мы ищем аналитика в команду развития event-... NaN NaN NaN NaN 55.695905 37.625361 От 1 года до 3 лет Тульская Серпуховско-Тимирязевская 55.709610 37.622569
3289 47325529 Strategy Partners Аналитик (стратегический консалтинг) ['Английский язык', 'MS PowerPoint', 'Аналитич... Полный день <p><strong>Strategy Partners </strong>(http://... NaN NaN NaN NaN 55.751262 37.586318 От 1 года до 3 лет Смоленская Арбатско-Покровская 55.747713 37.583802
3294 53169751 Т1 Консалтинг Младший консультант/бизнес-аналитик ['Английский язык', 'MS PowerPoint', 'Подготов... Полный день <p><strong>Т1 Консалтинг – </strong>российская... NaN NaN NaN NaN 55.708354 37.652705 От 1 года до 3 лет Автозаводская Замоскворецкая 55.706634 37.657008
3296 53150521 ИНТЕР РАО ИТ Старший аналитик НСМ ['Обучение и развитие', 'Управление проектами'... Полный день <p>Приглашаем на работу в ИТ-компанию, входящу... NaN NaN NaN NaN 55.730152 37.567815 От 3 до 6 лет Спортивная Сокольническая 55.722388 37.562041
3297 51710996 O'STIN Аналитик товарной категории [] Полный день <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... NaN NaN NaN NaN 55.792589 37.527588 От 1 года до 3 лет Аэропорт Замоскворецкая 55.800441 37.530477

1298 rows × 17 columns

In [9]:
arr = df_new.groupby('address.metro.station_name').count().reset_index().rename(columns = {'id' : 'line_count'})[['address.metro.station_name', 'line_count']]
df_for_map = df_new.merge(arr, how = 'outer', on = 'address.metro.station_name')
df_for_map
Out[9]:
id employer.name name key_skills schedule.name description salary.from salary.to salary.currency salary.gross lat lng experience.name address.metro.station_name address.metro.line_name address.metro.lat address.metro.lng line_count
0 54029828 Сбербанк Middle / Senior Java Developer (SberDevices) ['Java', 'Kotlin', 'Spring'] Полный день <p>Приглашаем в нашу команду специалистов, кот... NaN NaN NaN NaN 55.741338 37.531127 От 3 до 6 лет Кутузовская Филевская 55.740544 37.534100 43
1 53834398 Сбербанк Senior Python-разработчик в Цифровые поверхнос... ['Python', 'Apache Kafka', 'Apache Ignite', 'A... Полный день <p>SberDevices — уникальное IT-пространство вн... NaN NaN NaN NaN 55.741338 37.531127 От 3 до 6 лет Кутузовская Филевская 55.740544 37.534100 43
2 54029735 Сбербанк Java-разработчик (NLP / SberDevices) ['Spring Framework', 'SQL', 'PostgreSQL', 'Jav... Полный день <p><strong>SberDevices</strong> — уникальное I... NaN NaN NaN NaN 55.740421 37.532071 От 1 года до 3 лет Кутузовская МЦК 55.740833 37.533333 43
3 52685036 Сбербанк Qlik Sense разработчик ['Hadoop', 'SQL', 'Java', 'Jenkins', 'PostgreS... Полный день <p>Наша задача реализовать новое прикладное ко... NaN NaN NaN NaN 55.741338 37.531127 От 1 года до 3 лет Кутузовская Филевская 55.740544 37.534100 43
4 53834387 Сбербанк Python-разработчик в Цифровые поверхности Салю... ['Python', 'Django Framework', 'PostgreSQL', '... Полный день <p>SberDevices — уникальное IT-пространство вн... NaN NaN NaN NaN 55.741338 37.531127 От 1 года до 3 лет Кутузовская Филевская 55.740544 37.534100 43
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1293 52563054 Аналитическая компания АРЭНСИ Фарма Специалист по обработке данных ['MS Access', 'VBA', 'SQL', 'MS SQL', 'Базы да... Полный день <strong>Обязанности:</strong> <ul> <li>Работа ... 50000.0 50000.0 RUR 0.0 55.864005 37.677292 От 1 года до 3 лет Бабушкинская Калужско-Рижская 55.870641 37.664341 1
1294 52801356 БезРутины Бизнес-аналитик (бизнес-ассистент с экспертным... ['Аналитическое мышление', 'MS Excel', 'Сводны... Полный день <p><strong>GoFoods </strong>— российская компа... 100000.0 NaN RUR 0.0 55.585026 37.473626 От 1 года до 3 лет Коммунарка Сокольническая 55.559765 37.468716 1
1295 53988196 RALF RINGER Старший экономист-аналитик ['План-фактный анализ бюджета', 'Анализ текущи... Полный день <strong>Обязанности:</strong> <ol> <li>Подгото... NaN 100000.0 RUR 0.0 55.814264 37.735117 От 3 до 6 лет Бульвар Рокоссовского Сокольническая 55.814916 37.732227 2
1296 51844115 Черкизово, Группа предприятий Бизнес-аналитик ['Производственное планирование', 'Английский ... Полный день <strong>Обязанности:</strong> <ul> <li>Лидиров... NaN NaN NaN NaN 55.820582 37.732916 От 3 до 6 лет Бульвар Рокоссовского Сокольническая 55.814916 37.732227 2
1297 53009958 ТТФ Инвестиционный аналитик ['Финансовое моделирование', 'Финансовый анали... Полный день <strong>Обязанности:</strong> <p>- Финансовое ... NaN NaN NaN NaN NaN NaN От 3 до 6 лет Воробьевы горы Сокольническая 55.709169 37.557293 1

1298 rows × 18 columns

In [10]:
fig = px.scatter_mapbox(
    df_for_map,  # таблица с данными
    lat='address.metro.lat', lon='address.metro.lng',  # колонки с координатами
    color = 'address.metro.line_name',
    center=dict(lat=55.7737, lon=37.5717),
    zoom=10,
    size = df_for_map['line_count'],
    size_max = 14,
    mapbox_style='carto-positron'
)
fig.show();

Какие выводы можно сделать из построенных графиков?

1) В большинстве случаев работодатели требуют от сотрудников опыт $1$ год. Также много работодателей требует опыт от $1$ до $3$ лет. Очень мало компаний просят опыта больше $3$ лет. Связано это, скорее всего, с тем, что профессия относительно молодая.

2) Подавляющее большинство компаний связаны так или иначе с финансами, консалтингом и бизнес-сферой. Лишь малое количество специализируется в других отраслях (соц. сети, логистика и т.д.). Думаю, это связано с тем, что бизнес недавно только начал входить в сферу Анализа Данных, потому что до недавнего времени для бизнеса России это все было черным ящиком. Также можно выделить лидеров: Сбербанк, Иннотех, Тинькоф.

3) Большинство вакансий, мест работы сконцентрировано в пределах Мкада. Как правило между МКАДом и Садовым кольцом. Ну опять же, стоит понимать, что речь идет не о ресторанах и кафе, которые могут стремиться к центру для получения выгоды. От расположения компании мало что зависит. Поэтому такое "среднее" расположение между МКАДом и Садовым кольцом вполне себе уместно. Стоит также учесть то, что многие программисты работают на уделенке, их присутствие в офисе не везде обязательно.